/*
*/

package rosas.lou.weatherclasses;

import java.util.*;
import java.lang.*;
import rosas.lou.weatherclasses.*;
import gnu.io.*;

import com.dalsemi.onewire.*;
import com.dalsemi.onewire.adapter.*;
import com.dalsemi.onewire.container.*;

public class IButton{
   private Units units;
   private MissionLog missionLog;
   private String name;
   private String address;
   private double heatIndex = Double.NaN;
   private double dewPoint  = Double.NaN;
   //
   private List<Double> dewpointList      = null;
   private List<Double> heatIndexList     = null;
   private List<Double> humidityList      = null;
   private List<Date>   humidityTimeList  = null;   
   private List<Double> temperatureList   = null;
   private List<Date>   tempTimeList      = null;

   //Put listeners in a list to handle multiple listeners
   private List<MemoryListener> ml_List   = null;
   private List<MissionListener> mis_List = null;
   private List<LogListener> log_List     = null;
   
   //*********************Public Methods***************************
   /*
   */
   public IButton(){
      this.findSensors();
      this.setUnits(Units.METRIC);
   }
   
   /*
   */
   public IButton(String name, String address){
      this.setName(name);
      this.setAddress(address);
      this.setUpMissionLog();
      this.setUnits(Units.METRIC);
   }
   
   /*
   Register a Log Listener
   */
   public void addLogListener(LogListener ll){
      try{
         this.log_List.add(ll);
      }
      catch(NullPointerException npe){
         //Save the data off in a Vector
         this.log_List = new Vector<LogListener>();
         this.log_List.add(ll);
      }
   }
   
   /*
   Register a Memory Listener
   */
   public void addMemoryListener(MemoryListener ml){
      try{
         this.ml_List.add(ml);
      }
      catch(NullPointerException npe){
         //Save the data off in a Vector
         this.ml_List = new Vector<MemoryListener>();
         this.ml_List.add(ml);
      }
   }
   
   /*
   Register a Mission Listener
   */
   public void addMissionListener(MissionListener ml){
      try{
         this.mis_List.add(ml);
      }
      catch(NullPointerException npe){
         this.mis_List = new Vector<MissionListener>();
         this.mis_List.add(ml);
      }
   }
   
   /*
   */
   public void clearMemory(){
      String memoryEventString = new String();
      try{
         this.missionLog.clearLog();
         memoryEventString = new String("Memory Cleared ");
         memoryEventString = memoryEventString.concat("on iButton");
         memoryEventString = memoryEventString.concat(" device");
      }
      catch(MemoryException me){
         memoryEventString = new String(me.getMessage());
      }
      catch(NullPointerException npe){
         npe.printStackTrace();
         memoryEventString = new String(npe.getMessage());
      }
      finally{
         this.publishMemoryEvent(memoryEventString);
      }
   }
   
   /*
   */
   public String getAddress(){
      return this.address;
   }
   
   /*
   */
   public MissionLog getMissionLog(){
      return this.missionLog;
   }
   
   /*
   */
   public String getName(){
      return this.name;
   }
   
   /*
   */
   public Units getUnits(){
      return this.units;
   }
   
   /*
      Need both the Temperature and Humidity for this to work
   */
   public void requestDewpointData(){
      this.dewpointList = new LinkedList<Double>();
      try{
         //Temperature Time List Iterator
         Iterator<Date> tti = this.tempTimeList.iterator();
         //Humidity Time List Iterator
         Iterator<Date> hti = this.humidityTimeList.iterator();
         boolean bothTheSame = true;
         //In order for this calculation to be accurate, BOTH the
         //Temperature and Humidity need to be measured at the same
         //time:  if this is not the case, there is no guarantee of
         //the accuracy of the calculation
         while(tti.hasNext() && bothTheSame){
            long tti_time = ((Date)tti.next()).getTime();
            long hti_time = ((Date)hti.next()).getTime();
            bothTheSame   = (tti_time == hti_time);
         }
         if(bothTheSame){
            this.calculateDewpoint();
         }
         else{
            String les=new String("Humidity and Temperature Data");
            les = les.concat(" recorded at wrong times");
            this.dewpointList.add(new Double(Double.NaN));
            this.publishDewpointEvent(les, this.dewpointList);
         }
      }
      catch(IndexOutOfBoundsException ibe){
         String les = new String(ibe.getMessage());
         this.dewpointList.add(new Double(Double.NaN));
         this.publishDewpointEvent(les, this.dewpointList);
      }
      catch(NullPointerException npe){
         String les = new String(npe.getMessage());
         this.dewpointList.add(new Double(Double.NaN));
         this.publishDewpointEvent(les, this.dewpointList);
      }
      
   }
   
   /*
   */
   public void requestHeatIndexData(){
      this.heatIndexList = new LinkedList<Double>();
      try{
         //Temperature Time List Iterator
         Iterator<Date> tti = this.tempTimeList.iterator();
         //Humidity Time List Iterator
         Iterator<Date> hti = this.humidityTimeList.iterator();
         boolean bothTheSame = true;
         while(tti.hasNext() && bothTheSame){
            long tti_time = ((Date)tti.next()).getTime();
            long hti_time = ((Date)hti.next()).getTime();
            if(tti_time != hti_time){
               bothTheSame = false;
            }
         }
         if(bothTheSame){
            this.calculateHeatIndex();
         }
         else{
            String les=new String("Humidity and Temperature Data");
            les = les.concat(" recorded at wrong times");
            this.heatIndexList.add(new Double(Double.NaN));
            this.publishHeatIndexEvent(les, this.heatIndexList);
         }
      }
      catch(IndexOutOfBoundsException ibe){
         String les = new String(ibe.getMessage());
         this.heatIndexList.add(new Double(Double.NaN));
         this.publishHeatIndexEvent(les, this.heatIndexList);
      }
      catch(NullPointerException npe){
         String les = new String(npe.getMessage());
         this.heatIndexList.add(new Double(Double.NaN));
         this.publishHeatIndexEvent(les, this.heatIndexList);
      }
   }
   
   /*
   Get mission data (Temperature data in the current Units that are
   set)
   */
   public void requestMissionData
   (
      boolean forTemperature,
      boolean forHumidity
   ){
      this.requestMissionData(forTemperature,
                                     forHumidity, this.getUnits());
   }
   
   /*
   */
   public void requestMissionData
   (
      boolean forTemperature,
      boolean forHumidity,
      Units   units
   ){
      this.setUnits(units);
      if(forTemperature){
         this.requestTemperatureTimeData();
         this.requestTemperatureData(this.getUnits());
      }
      if(forHumidity){
         this.requestHumidityTimeData();
         this.requestHumidityData();
      }
   }
   
   /*
   Start a mission with the default sample rate set:  600 sec
   (10 min)
   */
   public void startMission(){
      this.startMission(MissionLog.DEFAULT_LOGGING_RATE);
   }
   
   /*
   Start a mission with a selected sample rate:  entered in seconds.
   This might mean the sample time needs to be translated from hours
   or minutes to seconds.
   */
   public void startMission(int sampleRate){
      String missionEventString = new String();
      try{
         //Get the Mission Log (better way of doing this, I feel)
         MissionLog ml = this.getMissionLog();
         ml.startLogging(sampleRate);
         missionEventString = new String("Mission Started on ");
         missionEventString = missionEventString.concat("iButton");
         missionEventString = missionEventString.concat(" device");
         missionEventString = missionEventString.concat(" with a ");
         missionEventString = missionEventString.concat("sample ");
         missionEventString = missionEventString.concat("time of:");
         missionEventString = missionEventString.concat(" " + sampleRate);
         missionEventString = missionEventString.concat(" seconds");
      }
      catch(MissionException me){
         missionEventString = new String(me.getMessage());
      }
      catch(NullPointerException npe){
         missionEventString = new String(npe.getMessage());
      }
      finally{
         this.publishMissionEvent(missionEventString);
      }
   }
   
   /*
   Stop the current mission
   */
   public void stopMission(){
      String missionEventString = new String();
      try{
         MissionLog ml = this.getMissionLog();
         ml.stopLogging();
         missionEventString = new String("Mission Stopped on ");
         missionEventString = missionEventString.concat("iButton");
         missionEventString = missionEventString.concat(" device");
      }
      catch(MissionException me){
         missionEventString = new String(me.getMessage());
      }
      catch(NullPointerException npe){
         missionEventString = new String(npe.getMessage());
      }
      finally{
         this.publishMissionEvent(missionEventString);
      }
   }
   
   /*
   Override the toString() method from the Object Class
   */
   public String toString(){
      return new String(this.getName()+", "+this.getAddress());
   }
   
   //**********************Private Methods*************************
   
   /*
   Calculate the dewpoint for a given pair of humidity and
   temperature sensors.  This is based on the temperature and
   humidty sensor stacks and is based on the assumption that
   That each temp sensor in the temperature stack corresponds 
   to an exact humidity sensor at the same position in the
   humidity stack.  The dewpoint is a formulaic calculation
   based on temperature and relative humidity and is an
   approximation.  The actual calculation depends upon wetbulb
   and dry bulb measurements.  This is an approximation based on
   the Manus-Tetens formula.
   Td = (243.12 * alpha[t,RH])/(17.62 - alpha[t, RH])
   where alpha[t,RH] = (17.62*t/(243.12 + t)) + ln(RH/100)
   and 0.0 < RH < 100.0.
   Temperature -45 to 60 degrees celsius
   */
   public void calculateDewpoint(){
      final double l = 243.12;  //lambda
      final double b =  17.62;  //Beta
      //This is needed since the humidity recorded on the iButton
      //CAN be below 0.
      final double MINIMUMHUMIDITY = 0.;
      
      String les      = new String();
      Double dewpoint = Double.NaN; //Default Dewpoint Value
      List<Double> temp_l = this.temperatureList;
      List<Double> humi_l = this.humidityList;
      try{
         les = new String("Dew Point Calculated");
         //Since the formula is for units of Celsius, need to
         //convert to Celsius first (if units are not in
         //Celsius)
         if(this.getUnits() == Units.ENGLISH){
            this.convertFahrenheitToCelsius(temp_l);
         }
         else if(this.getUnits() == Units.ABSOLUTE){
            this.convertKelvinToCelsius(temp_l);
         }
         for(int i = 0; i < temp_l.size(); i++){
            dewpoint = Double.NaN;
            Double tempd = temp_l.get(i);
            Double humid = humi_l.get(i);
            if(!(tempd.isNaN() || humid.isNaN())){
               //Now, for the calculation, get the appropriate 
               //temperature and relative humidity
               double tc = tempd.doubleValue();
               double rh = humid.doubleValue();
               //Only calculate the deewpoint if the humidity> 0.
               if(rh > MINIMUMHUMIDITY){
                  double alpha = ((b*tc)/(l+tc))+Math.log(rh*0.01);
                  //This will now give us the dewpiont in degrees
                  //celsius. Now, need to go ahead and figure out
                  //the units needed.
                  double dp = (l * alpha)/(b - alpha);
                  dewpoint = new Double(dp);
               }
            }
            this.dewpointList.add(dewpoint);
         }
         //Convert the temperature back to the appropriate units
         if(this.getUnits() == Units.ENGLISH){
            this.convertCelsiusToFahrenheit(temp_l);
            this.convertCelsiusToFahrenheit(this.dewpointList);
         }
         else if(this.getUnits() == Units.ABSOLUTE){
            this.convertCelsiusToKelvin(temp_l);
            this.convertCelsiusToKelvin(this.dewpointList);
         }
      }
      catch(IndexOutOfBoundsException ibe){
         les = new String(ibe.getMessage());
         this.dewpointList.add(new Double(Double.NaN));
      }
      catch(NullPointerException npe){
         les = new String(npe.getMessage());
         this.heatIndexList.add(new Double(Double.NaN));
      }
      finally{
         this.publishDewpointEvent(les, this.dewpointList);
      }
   }

   /*
   Calculate the heat index for a given pair of humidity and
   temperature sensors.  This is based on the temperature and
   humidity sensor stacks and is based on the assumption that
   each temperature sensor in the temperature stack corresponds
   to an excact humidity sensor at the same position in the
   humidity stack.  The heat index is a formulaic calculation
   based on temprature and relative humidity and is an
   approximation (although pretty good) which is based on sixteen
   calculations.
   heatindex = 16.923                            +
               (.185212*tf)                      +
               (5.37941 * rh)                    -
               (.100254*tf*rh)                   +
               ((9.41685 * 10^-3) * tf^2)        +
               ((7.28898 * 10^-3) * rh^2)        +
               ((3.45372*10^-4) * tf^2*rh)       -
               ((8.14971*10^-4) * tf *rh^2)      +
               ((1.02102*10^-5) * tf^2 * rh^2)   -
               ((3.8646*10^-5) * tf^3)           +
               ((2.91583*10^-5) * rh^3)          +
               ((1.42721*10^-6) * tf^3 * rh)     +
               ((1.97483*10^-7) * tf * rh^3)     -
               ((2.18429*10^-8) * tf^3 * rh^2)   +
               ((8.43296*10^-10) * tf^2 * rh^3)  -
               ((4.81975*10^-11)*t^3*rh^3)
   
   NOTE:  The Heat Index Calculation becomes inaccurate at a Dry Bulb
          less than 70 F.  If that is the case, the default value
          is set.  For those values, the System will have to determine
          The reason for the default Heat Index.  It is up to the
          System to figure out the appropriateness of the Heat Index
          data for display.
   */
   private void calculateHeatIndex(){
      final double MINIMUMTEMP = 70.;
      final double MINIMUMHUMI = 0.;
      String les          = new String();
      Double heatIndex    = Double.NaN;
      List<Double> temp_l = this.temperatureList;
      List<Double> humi_l = this.humidityList;
      try{
         les = new String("Heat Index Calculated");
         //Since the formula is for units of Fahrenheit, need to
         //convert to Fahrenheit first
         if(this.getUnits() == Units.METRIC){
            this.convertCelsiusToFahrenheit(temp_l);
         }
         else if(this.getUnits() == Units.ABSOLUTE){
            this.convertKelvinToFahrenheit(temp_l);
         }
         for(int i = 0; i < temp_l.size(); i++){
            heatIndex = Double.NaN;
            Double tempd = temp_l.get(i);
            Double humid = humi_l.get(i);
            if(!(tempd.isNaN() || humid.isNaN())){
               double tf = tempd.doubleValue();
               double rh = humid.doubleValue();
               if(tf > MINIMUMTEMP && rh > MINIMUMHUMI){
                  double hi =  16.923;
                  hi += (.185212 * tf);
                  hi += (5.37941 * rh);
                  hi -= ((.100254) * tf * rh);
                  hi += ((9.41685 * .001) * tf * tf);
                  hi += ((7.28898 * .001) * rh * rh);
                  hi += ((3.45372 * .0001) * tf * tf * rh);
                  hi -= ((8.14971 * .0001) * tf * rh * rh);
                  hi += ((1.02102 * .00001) * tf * tf * rh * rh);
                  hi -= ((3.8646  * .00001) * tf * tf * tf);
                  hi += ((2.91583 * .00001) * rh * rh * rh);
                  hi += ((1.42721 * .000001)* tf * tf * tf * rh);
                  hi += ((1.97483 * .0000001) * tf * rh * rh * rh);
                  hi -= ((2.18429 * .00000001) *tf*tf*tf* rh * rh);
                  hi += ((8.43196 * .0000000001) *tf*tf*rh*rh* rh);
                  hi -=((4.81975 * .00000000001)*tf*tf*tf*rh*rh*rh);
                  heatIndex = new Double(hi);
               }
            }
            this.heatIndexList.add(heatIndex);
         }
         //Convert the temperature to the appropriate units:
         //if the Units are NOT in ENGLISH
         if(this.getUnits() == Units.METRIC){
            this.convertFahrenheitToCelsius(temp_l);
            this.convertFahrenheitToCelsius(this.heatIndexList);
         }
         else if(this.getUnits() == Units.ABSOLUTE){
            this.convertFahrenheitToKelvin(temp_l);
            this.convertFahrenheitToKelvin(this.heatIndexList);
         }
      }
      catch(IndexOutOfBoundsException ibe){
         les = new String(ibe.getMessage());
         this.heatIndexList.add(new Double(Double.NaN));
         
      }
      catch(NullPointerException npe){
         les = new String(npe.getMessage());
         this.heatIndexList.add(new Double(Double.NaN));
      }
      finally{
         this.publishHeatIndexEvent(les, this.heatIndexList);
      }
   }
   
   /*
   */
   private void convertCelsiusToFahrenheit(List tempList){
      //First, check to see if the list is empty
      if(!tempList.isEmpty()){
         for(int i = 0; i < tempList.size(); i++){
            try{
               Double tempd = (Double)tempList.get(i);
               if(!tempd.isNaN()){
                  double temp  = tempd.doubleValue();
                  temp = WeatherConvert.celsiusToFahrenheit(temp);
                  //Replace the element in the List as needed
                  tempList.set(i, new Double(temp));
               }
            }
            //This should never happen
            catch(IndexOutOfBoundsException ibe){
               ibe.printStackTrace();
            }
         }
      }
   }
   
   /*
   */
   private void convertCelsiusToKelvin(List tempList){
      //First, check to see if the list is empty
      if(!tempList.isEmpty()){
         for(int i = 0; i < tempList.size(); i++){
            try{
               Double tempd = (Double)tempList.get(i);
               if(!tempd.isNaN()){
                  double temp  = tempd.doubleValue();
                  temp = WeatherConvert.celsiusToKelvin(temp);
                  //Replace the element in the List as needed
                  tempList.set(i, new Double(temp));
               }
            }
            //This should never happen
            catch(IndexOutOfBoundsException ibe){
               ibe.printStackTrace();
            }
         }
      }      
   }
 
   /*
   */
   private void convertFahrenheitToCelsius(List tempList){
      //First, check to see if the list is empty
      if(!tempList.isEmpty()){
         for(int i = 0; i < tempList.size(); i++){
            try{
               Double tempd = (Double)tempList.get(i);
               if(!tempd.isNaN()){
                  double temp  = tempd.doubleValue();
                  temp = WeatherConvert.fahrenheitToCelsius(temp);
                  //Replace the element in the List as needed
                  tempList.set(i, new Double(temp));
               }
            }
            //This should never happen
            catch(IndexOutOfBoundsException ibe){
               ibe.printStackTrace();
            }
         }
      }
   }
   
   /*
   */
   private void convertFahrenheitToKelvin(List tempList){
      //First, check to see if the list is empty
      if(!tempList.isEmpty()){
         for(int i = 0; i < tempList.size(); i++){
            try{
               Double tempd = (Double)tempList.get(i);
               if(!tempd.isNaN()){
                  double temp  = tempd.doubleValue();
                  temp = WeatherConvert.fahrenheitToKelvin(temp);
                  //Replace the element in the List as needed
                  tempList.set(i, new Double(temp));
               }
            }
            //This should never happen
            catch(IndexOutOfBoundsException ibe){
               ibe.printStackTrace();
            }
         }
      }
   }
   
   /*
   */
   private void convertKelvinToCelsius(List tempList){
      //First, check to see if the list is empty
      if(!tempList.isEmpty()){
         for(int i = 0; i < tempList.size(); i++){
            try{
               Double tempd = (Double)tempList.get(i);
               if(!tempd.isNaN()){
                  double temp = tempd.doubleValue();
                  temp = WeatherConvert.kelvinToCelsius(temp);
                  //Replace the element in the List as needed
                  tempList.set(i, new Double(temp));
               }
            }
            //This should never happen
            catch(IndexOutOfBoundsException ibe){
               ibe.printStackTrace();
            }
         }
      }
   }
   
   /*
   */
   private void convertKelvinToFahrenheit(List tempList){
      //First, check to see if the list is empty
      if(!tempList.isEmpty()){
         for(int i = 0; i < tempList.size(); i++){
            try{
               Double tempd = (Double)tempList.get(i);
               if(!tempd.isNaN()){
                  double temp  = tempd.doubleValue();
                  temp = WeatherConvert.kelvinToFahrenheit(temp);
                  //Replace the element in the List as needed
                  tempList.set(i, new Double(temp));
               }
            }
            //This should never happen
            catch(IndexOutOfBoundsException ibe){
               ibe.printStackTrace();
            }
         }
      }
   }
   
   /*
   */
   private void findSensors(){
      PortSniffer ps = new PortSniffer(PortSniffer.PORT_USB);
      Hashtable hash = ps.findPorts();
      Enumeration ports = hash.keys();
      /*Finding this sensor is more "specialized" than finding
      the weather sensors-->because there truthfully ONLY
      one Sensor:  the iButton, which I can get BOTH the
      stored temperature and humidity data.*/
      while(ports.hasMoreElements()){
         //Get the next Key in the Hashtable
         String port = (String)ports.nextElement();
         //Now, get the name and address of the sensor:
         //port is the key into the Hashtable
         Stack sensorData = (Stack)hash.get(port);
         Enumeration element = sensorData.elements();
         while(element.hasMoreElements()){
            String name    = (String)element.nextElement();
            String address = (String)element.nextElement();
            if(!name.equals("DS1990A")){
               /*Since this is a Thermochron iButton, I should only
               have one name and address (asside from the adapter
               address*/
               this.setName(name);
               this.setAddress(address);
            }
         }
      }
      this.setUpMissionLog();
   }
   
   /*
   */
   private void publishDewpointEvent
   (
      String eventString,
      List   list
   ){
      LogEvent evt =
               new LogEvent(this,eventString,list,this.getUnits());
      try{
         Iterator<LogListener> i = this.log_List.iterator();
         while(i.hasNext()){
            (i.next()).onDewpointLogEvent(evt);
         }
      }
      //If this exception occurs, there are no Log Listeners,
      //regardless, so the only thing to do is alert through the
      //"typical channels"
      catch(NullPointerException npe){
         npe.printStackTrace();
      }
   }
   
   /*
   */
   private void publishHeatIndexEvent
   (
      String eventString,
      List   list
   ){
      LogEvent evt =
            new LogEvent(this, eventString, list, this.getUnits());
      try{
         Iterator<LogListener> i = this.log_List.iterator();
         while(i.hasNext()){
            (i.next()).onHeatIndexLogEvent(evt);
         }
      }
      //If this exception occurs, there are no Log Listeners,
      //regardless, so the only thing to do is alert through the
      //"typical channels"
      catch(NullPointerException npe){
         npe.printStackTrace();
      }
   }
   
   /*
   */
   private void publishHumidityLogEvent
   (
      String eventString,
      List   list
   ){
      LogEvent evt = new LogEvent(this, eventString, list);
      try{
         Iterator<LogListener> i = this.log_List.iterator();
         while(i.hasNext()){
            (i.next()).onHumidityLogEvent(evt);
         }
      }
      //If this exception occurs, there are no Log Listeners,
      //regardless, so the only thing to do is alert through the
      //"typical channels"
      catch(NullPointerException npe){
         npe.printStackTrace();
      }
   }
   
   /*
   */
   private void publishHumidityTimeLogEvent
   (
      String eventString,
      List   list
   ){
      LogEvent evt = new LogEvent(this, eventString, list);
      try{
         Iterator<LogListener> i = this.log_List.iterator();
         while(i.hasNext()){
            (i.next()).onHumidityTimeLogEvent(evt);
         }
      }
      //If this exception occurs, there are no Log Listeners,
      //regardless, so the only thing to do is alert through the
      //"typical channels"
      catch(NullPointerException npe){
         npe.printStackTrace();
      }      
   }

   /*
   */
   private void publishMemoryEvent(String eventString){
      MemoryEvent evt = new MemoryEvent(this, eventString);
      try{
         Iterator<MemoryListener> i = this.ml_List.iterator();
         while(i.hasNext()){
            (i.next()).onMemoryEvent(evt);
         }
      }
      //If the exception occurs, there are no memory listeners,
      //regardless, so the only thing to do is aleart through
      //the "typical channels"
      catch(NullPointerException npe){
         npe.printStackTrace();
      }
   }
   
   /*
   */
   private void publishMissionEvent(String eventString){
      MissionEvent evt = new MissionEvent(this, eventString);
      try{
         Iterator<MissionListener> i = this.mis_List.iterator();
         while(i.hasNext()){
            (i.next()).onMissionEvent(evt);
         }
      }
      //If the exception occurs, there are no Mission listeners,
      //regardless, so the only thing to do is aleart through
      //the "typical channels"      
      catch(NullPointerException npe){
         npe.printStackTrace();
      }
   }
   
   /*
   */
   private void publishTemperatureLogEvent
   (
      String eventString,
      List   list
   ){
      LogEvent evt =
            new LogEvent(this, eventString, list, this.getUnits());
      try{
         Iterator<LogListener> i = this.log_List.iterator();
         while(i.hasNext()){
            (i.next()).onTemperatureLogEvent(evt);
         }
      }
      //If this exception occurs, there are no Log Listeners,
      //regardless, so the only thing to do is alert through the
      //"typical channels"
      catch(NullPointerException npe){
         npe.printStackTrace();
      }
   }
   
   /*
   */
   private void publishTemperatureTimeLogEvent
   (
      String eventString,
      List   list
   ){
      LogEvent evt = new LogEvent(this, eventString, list);
      try{
         Iterator<LogListener> i = this.log_List.iterator();
         while(i.hasNext()){
            (i.next()).onTemperatureTimeLogEvent(evt);
         }
      }
      //If this exception occurs, there are no Log Listeners,
      //regardless, so the only thing to do is alert through the
      //"typical channels"
      catch(NullPointerException npe){
         npe.printStackTrace();
      }      
   }
   
   /*
   */
   private void requestHumidityData(){
      this.humidityList = new LinkedList<Double>();
      String les        = new String();
      try{
         MissionLog ml  = this.getMissionLog();
         humidityList   = ml.requestHumidityLog();
         les = new String("Humidity Log Data Received");
         les = les.concat("\nand sent to the listeners");
      }
      catch(MissionException me){
         me.printStackTrace();
         les = new String(me.getMessage());
         //Indicate there was a problem
         humidityList.add(new Double(Double.NaN));
      }
      catch(NullPointerException npe){
         npe.printStackTrace();
         les = new String(npe.getMessage());
         //Indicate there was a problem
         humidityList.add(new Double(Double.NaN));
      }
      finally{
         this.publishHumidityLogEvent(les, this.humidityList);
      }
   }
   
   /*
   */
   private void requestHumidityTimeData(){
      this.humidityTimeList = new LinkedList<Date>();
      //Log Event String
      String les = new String();
      try{
         MissionLog ml = this.getMissionLog();
         this.humidityTimeList = ml.requestHumidityTimeLog();
         les = new String("Humidity Time Log");
      }
      catch(MissionException me){
         me.printStackTrace();
         les = new String(me.getMessage());
      }
      catch(NullPointerException npe){
         npe.printStackTrace();
         les = new String(npe.getMessage());
      }
      finally{
         this.publishHumidityTimeLogEvent(les, humidityTimeList);
      }
   }
   
   /*
   */
   private void requestTemperatureData(Units units){
      this.temperatureList = new LinkedList<Double>();
      //Log Event String
      String les           = new String();
      try{
         MissionLog ml   = this.getMissionLog();
         this.temperatureList = ml.requestTemperatureLog();
         if(units == Units.ABSOLUTE){
            this.convertCelsiusToKelvin(temperatureList);
         }
         else if(units == Units.ENGLISH){
            this.convertCelsiusToFahrenheit(temperatureList);
         }
         les = new String("Temperature Log Data Received");
         les = les.concat("\nand sent to the listeners");
      }
      catch(MissionException me){
         me.printStackTrace();
         les = new String(me.getMessage());
         //To indicate there was a problem
         this.temperatureList.add(new Double(Double.NaN));
      }
      catch(NullPointerException npe){
         npe.printStackTrace();
         les = new String(npe.getMessage());
         //To indicate there was a problem
         this.temperatureList.add(new Double(Double.NaN));
      }
      finally{
         this.publishTemperatureLogEvent(les, temperatureList);
      }
   }

   /*
   */
   private void requestTemperatureTimeData(){
      this.tempTimeList = new LinkedList<Date>();
      //Log Event String
      String les = new String();
      try{
         MissionLog ml = this.getMissionLog();
         this.tempTimeList = ml.requestTemperatureTimeLog();
         les = new String("Temperature Time Log");
      }
      catch(MissionException me){
         me.printStackTrace();
         les = new String(me.getMessage());
      }
      catch(NullPointerException npe){
         npe.printStackTrace();
         les = new String(npe.getMessage());
      }
      finally{
         this.publishTemperatureTimeLogEvent(les,tempTimeList);
      }
   }
   
   /*
   */
   private void setAddress(String address){
      this.address = new String(address);
   }
   
   /*
   */
   private void setName(String name){
      this.name = new String(name);
   }
   
   /*
   */
   private void setUnits(Units units){
      this.units = units;
   }
   
   /*
   */
   private void setUpMissionLog(){
      DSPortAdapter dspa = null;
      try{
         dspa = OneWireAccessProvider.getDefaultAdapter();
         this.missionLog = new MissionLog(new OneWireContainer41(
                                          dspa, this.getAddress()));
      }
      catch(OneWireIOException ioe){
         ioe.printStackTrace();
      }
      catch(OneWireException owe){
         owe.printStackTrace();
      }
   }

}